package com.qwc.blog.service.impl;

import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qwc.blog.common.constant.ConfigConstant;
import com.qwc.blog.common.constant.ResponseConstant;
import com.qwc.blog.common.exception.AuthenticationException;
import com.qwc.blog.common.exception.ResponseException;
import com.qwc.blog.entity.SysConfig;
import com.qwc.blog.entity.dto.LoginDto;
import com.qwc.blog.entity.dto.PwdUpdateDto;
import com.qwc.blog.service.ILoginService;
import com.qwc.blog.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;

/**
 * @author qiuwencong
 * @Date 2022/2/7 15:26
 * @Package com.qwc.blog.service.impl
 * @Description
 */
@Service
public class LoginServiceImpl implements ILoginService {

    @Autowired
    private TimedCache<String, String> cache;

    @Autowired
    private ISysConfigService sysConfigService;

    @Override
    public String authenticate(LoginDto dto) {
        Map<String, String> map = sysConfigService.configMap(ConfigConstant.LOGIN);
        if (map.containsKey(ConfigConstant.LOGIN_USERNAME)) {
            if (!dto.getUsername().equals(map.get(ConfigConstant.LOGIN_USERNAME))) {
                throw new ResponseException(ResponseConstant.USERNAME_MISTAKE);
            }
        } else {
            throw new ResponseException(ResponseConstant.USERNAME_NOT_CONFIG);
        }
        if (map.containsKey(ConfigConstant.LOGIN_PASSWORD)) {
            if (!checkPassword(map.get(ConfigConstant.LOGIN_PASSWORD), dto.getPassword())) {
                throw new ResponseException(ResponseConstant.PASSWORD_MISTAKE);
            }
        } else {
            throw new ResponseException(ResponseConstant.PASSWORD_NOT_CONFIG);
        }
        return createToken();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePassword(PwdUpdateDto dto) {
        SysConfig config = sysConfigService.getOne(Wrappers.<SysConfig>lambdaQuery()
                .eq(SysConfig::getName, ConfigConstant.LOGIN)
                .eq(SysConfig::getConfigKey, ConfigConstant.LOGIN_PASSWORD));
        String password = config.getConfigValue();
        if (!checkPassword(password,dto.getOldPwd())) {
            throw new ResponseException(ResponseConstant.OLD_PASSWORD_MISTAKE);
        }
        if(checkPassword(password,dto.getNewPwd())){
            throw new ResponseException(ResponseConstant.NEW_PASSWORD_EQUALS);
        }
        if(!dto.getNewPwd().equals(dto.getNewAgainPwd())){
            throw new ResponseException(ResponseConstant.AGAIN_PASSWORD_MISTAKE);
        }
        config.setConfigValue(DigestUtil.bcrypt(dto.getNewPwd()));
        return sysConfigService.updateById(config);
    }

    /**
     * 创建token并保存
     *
     * @return
     */
    private String createToken() {
        Map<String, String> map = sysConfigService.configMap(ConfigConstant.TOKEN);
        String token = RandomUtil.randomString(Integer.valueOf(map.get(ConfigConstant.TOKEN_LENGTH)));
        cache.put(ConfigConstant.TOKEN, token, Long.valueOf(map.get(ConfigConstant.TOKEN_EXPIRE)));
        return token;
    }

    /**
     * 认证密码
     *
     * @param password
     * @param dtoPwd
     * @return
     */
    private boolean checkPassword(String password, String dtoPwd) {
        return DigestUtil.bcryptCheck(dtoPwd, password);
    }
}
